S.Ct.Container = function (div) {
    let me = this;
    Q.doSuperConstructor(me, S.Ct.Container, [div]);
    me.addCustomInteractions();
    me.addInteractionDispatcher();
};

S.Ct.Container.prototype = {
    xtype: 'container',
    /**
     * 按名称搜索
     * @param name 不区分大小写，模糊匹配
     * @returns 第一个搜索到的对象
     */
    search: function (name) {
        let me = this, results = me.searchResults || {}, result;
        name = name.trim().toLowerCase();
        if (!Ext.isEmpty(name)) {
            if (results.name == name) { // 名称相同，表示同一次搜索，循环返回
                results.index++;
                if (results.index >= results.datas.length) {
                    results.index = 0;
                }
                result = results.datas[results.index];
            } else {
                results.datas = [];
                me.graphModel.forEach((e) => {
                    if (-1 < e.name.toLowerCase().search(name)) {
                        results.datas.push(e);
                    }
                });
                results.index = -1;
                results.name = name;
                if (results.datas.length > 0) {
                    results.index = 0;
                    result = results.datas[0];
                }
            }
            me.searchResults = results;
        }
        return result;
    },
    /**
     * 按id路径搜索，如果没有找到，继续找上级
     * @param path
     * @returns {*}
     */
    findByPath: function (path) {
        let gm = this.graphModel, ids = path.split('/'), result;
        for (let i = ids.length - 1; i >= 0; i--) {
            gm.forEachNode((e) => {
                if (e.data && e.data.id == ids[i]) {
                    result = e;
                    return;
                }
            });
            if (result) {
                return result;
            }
        }
    },
    /**
     * 在graph中选中指定的组件，并将组件自动居中
     * @param item
     */
    select: function (item) {
        let me = this;
        if (item) {
            me.setSelection(item);
            let bounds = me.getUIBounds(item);
            if (bounds) {
                me.centerTo(bounds.cx, bounds.cy, Math.max(2, me.scale), true);
            }
        }
    },

    fireEvent: function (eventName, detail) {
        let me = this, event = new CustomEvent(eventName, {
            detail: detail,
        });
        let ct = me.canvasPanel;
        if (ct.dispatchEvent) {
            ct.dispatchEvent(event);
        } else if (ct.fireEvent) {
            ct.fireEvent(event);
        }
    },

    addCustomInteractions() {
        let me = this;
        me.addCustomInteraction({
            onclick: function (evt) {
                me.onClick && me.onClick(evt);
                me.fireEvent('onclick', evt);
            },
            ondblclick: function (evt) {
                me.onDblClick && me.onDblClick(evt);
                me.fireEvent('ondblclick', evt);
            },
            onmousemove: function (evt) {
                let data = evt.getData();
                me.cursor = data && me.isSelectable(data) ? 'pointer' : null;
            }
        });
    },

    addInteractionDispatcher(graph) {
        let me = this;
        this.interactionDispatcher.addListener(function (evt) {
            switch (evt.kind) {
                case Q.InteractionEvent.SELECT:
                case Q.InteractionEvent.SELECT_END:
                    me.fireEvent('onselectchange', evt);
            }
        });
    }

}

Q.extend(S.Ct.Container, Q.Graph);
